home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / linux / tools / gtar10.lha / create.c < prev    next >
C/C++ Source or Header  |  1992-09-09  |  31KB  |  1,316 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  *
  25.  * @(#)create.c 1.36 11/6/87 - gnu
  26.  */
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <stdio.h>
  30.  
  31. #ifndef V7
  32. #include <fcntl.h>
  33. #endif
  34.  
  35. #ifndef    __MSDOS__
  36. #include <sys/file.h>
  37. #include <sys/param.h>        /* for MAXPATHLEN */
  38. #include <pwd.h>
  39. #include <grp.h>
  40. #endif
  41.  
  42. #ifdef BSD42
  43. #include <sys/dir.h>
  44. #else
  45. #ifdef __MSDOS__
  46. #include "msd_dir.h"
  47. #else
  48. #ifdef USG
  49. #ifdef NDIR
  50. #include <ndir.h>
  51. #else
  52. #include <dirent.h>
  53. #endif
  54. #ifndef DIRECT
  55. #define direct dirent
  56. #endif
  57. #define DP_NAMELEN(x) strlen((x)->d_name)
  58. #else
  59. /*
  60.  * FIXME: On other systems there is no standard place for the header file
  61.  * for the portable directory access routines.  Change the #include line
  62.  * below to bring it in from wherever it is.
  63.  */
  64. #include "ndir.h"
  65. #endif
  66. #endif
  67. #endif
  68.  
  69. #ifndef DP_NAMELEN
  70. #define DP_NAMELEN(x)    (x)->d_namlen
  71. #endif
  72.  
  73. #ifdef USG
  74. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  75. #endif
  76.  
  77. /*
  78.  * V7 doesn't have a #define for this.
  79.  */
  80. #ifndef O_RDONLY
  81. #define    O_RDONLY    0
  82. #endif
  83.  
  84. /*
  85.  * Most people don't have a #define for this.
  86.  */
  87. #ifndef    O_BINARY
  88. #define    O_BINARY    0
  89. #endif
  90.  
  91. #ifndef MAXPATHLEN
  92. #define MAXPATHLEN 1024
  93. #endif
  94.  
  95. #include "tar.h"
  96. #include "port.h"
  97.  
  98. extern struct stat hstat;        /* Stat struct corresponding */
  99.  
  100. #ifndef __MSDOS__
  101. extern dev_t ar_dev;
  102. extern ino_t ar_ino;
  103. #endif
  104.  
  105. /* JF */
  106. extern struct name *gnu_list_name;
  107.  
  108. /*
  109.  * If there are no symbolic links, there is no lstat().  Use stat().
  110.  */
  111. #ifndef S_IFLNK
  112. #define lstat stat
  113. #endif
  114.  
  115. #ifndef __STDC__
  116. extern char    *malloc();
  117. extern char    *strcpy();
  118. extern char    *strncpy();
  119. extern void    bzero();
  120. extern void    bcopy();
  121. #endif
  122. extern int    errno;
  123.  
  124. extern void print_header();
  125.  
  126. union record *start_header();
  127. void finish_header();
  128. void finduname();
  129. void findgname();
  130. char *name_next();
  131. void to_oct();
  132. void dump_file();
  133.  
  134.  
  135. /* This code moved from tar.h since create.c is the only file that cares
  136.    about 'struct link's.  This means that other files might not have to
  137.    include sys/types.h any more.
  138.  */
  139.  
  140. struct link {
  141.     struct link    *next;
  142.     dev_t        dev;
  143.     ino_t        ino;
  144.     short        linkcount;
  145.     char        name[1];
  146. };
  147.  
  148. struct link    *linklist;    /* Points to first link in list */
  149.  
  150. static nolinks;            /* Gets set if we run out of RAM */
  151.  
  152. /*
  153.  * "Scratch" space to store the information about a sparse file before
  154.  * writing the info into the header or extended header
  155.  */
  156. /* struct sp_array     *sparsearray;*/
  157.  
  158. /* number of elts storable in the sparsearray */
  159. /*int     sparse_array_size = 10;*/
  160.  
  161. void
  162. create_archive()
  163. {
  164.     register char    *p;
  165.     char *name_from_list();
  166.  
  167.     open_archive(0);        /* Open for writing */
  168.  
  169.     if(f_gnudump) {
  170.         char buf[MAXNAMLEN],*q,*bufp;
  171.  
  172.         collect_and_sort_names();
  173.  
  174.         while(p=name_from_list())
  175.             dump_file(p,-1);
  176.         /* if(!f_dironly) { */
  177.             blank_name_list();
  178.             while(p=name_from_list()) {
  179.                 strcpy(buf,p);
  180.                 if(p[strlen(p)-1]!='/')
  181.                     strcat(buf,"/");
  182.                 bufp=buf+strlen(buf);
  183.                 for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {
  184.                     if(*q=='Y') {
  185.                         strcpy(bufp,q+1);
  186.                         dump_file(buf,-1);
  187.                     }
  188.                 }
  189.             }
  190.         /* } */
  191.     
  192.     } else {
  193.         p = name_next(1);
  194.         if(!p)
  195.             dump_file(".", -1);
  196.         else {
  197.             do dump_file(p, -1);
  198.             while (p = name_next(1));
  199.         }
  200.     }
  201.  
  202.     write_mangled();
  203.     write_eot();
  204.     close_archive();
  205.     if(f_gnudump)
  206.         write_dir_file();
  207.     name_close();
  208. }
  209.  
  210. /*
  211.  * Dump a single file.  If it's a directory, recurse.
  212.  * Result is 1 for success, 0 for failure.
  213.  * Sets global "hstat" to stat() output for this file.
  214.  */
  215. void
  216. dump_file (p, curdev)
  217.     char    *p;            /* File name to dump */
  218.     int    curdev;            /* Device our parent dir was on */
  219. {
  220.     union record    *header;
  221.     char type;
  222.     extern char *save_name;        /* JF for multi-volume support */
  223.     extern long save_totsize;
  224.     extern long save_sizeleft;
  225.     union record    *exhdr;
  226.     char save_linkflag;
  227.     extern time_t new_time;
  228.     int sparse_ind = 0;
  229.  
  230.  
  231.     if(f_confirm && !confirm("add",p))
  232.         return;
  233.  
  234.     /*
  235.      * Use stat if following (rather than dumping) 4.2BSD's
  236.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  237.      * systems, is #define'd to stat anyway.
  238.      */
  239. #ifdef AIX
  240.     if (0 != f_follow_links ?
  241.         statx (p, &hstat, STATSIZE, STX_HIDDEN):
  242.         statx (p, &hstat, STATSIZE, STX_HIDDEN|STX_LINK))
  243. #else
  244.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  245. #endif /* AIX */
  246.     {
  247. badperror:
  248.         msg_perror("can't add file %s",p);
  249. badfile:
  250.         errors++;
  251.         return;
  252.     }
  253.  
  254. #ifdef AIX
  255.     if (S_ISHIDDEN (hstat.st_mode)) {
  256.         char *new = (char *)allocate (strlen (p) + 2);
  257.         if (new) {
  258.             strcpy (new, p);
  259.             strcat (new, "@");
  260.             p = new;
  261.         }
  262.     }
  263. #endif /* AIX */
  264.  
  265.     /* See if we only want new files, and check if this one is too old to
  266.        put in the archive. */
  267.     if(   f_new_files
  268.        && !f_gnudump
  269.         && new_time>hstat.st_mtime
  270.         && (hstat.st_mode&S_IFMT)!=S_IFDIR
  271.         && (f_new_files>1 || new_time>hstat.st_ctime)) {
  272.         if(curdev<0) {
  273.             msg("%s: is unchanged; not dumped",p);
  274.         }
  275.         return;
  276.     }
  277.  
  278. #ifndef __MSDOS__
  279.     /* See if we are trying to dump the archive */
  280.     if(ar_dev && hstat.st_dev==ar_dev && hstat.st_ino==ar_ino) {
  281.         msg("%s is the archive; not dumped",p);
  282.         return;
  283.     }
  284. #endif
  285.     /*
  286.      * Check for multiple links.
  287.      *
  288.      * We maintain a list of all such files that we've written so
  289.      * far.  Any time we see another, we check the list and
  290.      * avoid dumping the data again if we've done it once already.
  291.      */
  292.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  293.         register struct link    *lp;
  294.  
  295.     case S_IFREG:            /* Regular file */
  296. #ifdef S_IFCTG
  297.     case S_IFCTG:            /* Contigous file */
  298. #endif
  299. #ifdef S_IFCHR
  300.     case S_IFCHR:            /* Character special file */
  301. #endif
  302.  
  303. #ifdef S_IFBLK
  304.     case S_IFBLK:            /* Block     special file */
  305. #endif
  306.  
  307. #ifdef S_IFIFO
  308.     case S_IFIFO:            /* Fifo      special file */
  309. #endif
  310.  
  311.         /* First quick and dirty.  Hashing, etc later FIXME */
  312.         for (lp = linklist; lp; lp = lp->next) {
  313.             if (lp->ino == hstat.st_ino &&
  314.                 lp->dev == hstat.st_dev) {
  315.                 char *link_name = lp->name;
  316.  
  317.                 /* We found a link. */
  318.                 hstat.st_size = 0;
  319.                 header = start_header(p, &hstat);
  320.                 if (header == NULL) goto badfile;
  321.                 while(!f_absolute_paths && *link_name == '/') {
  322.                     static int link_warn = 0;
  323.  
  324.                     if (!link_warn) {
  325.                         msg("Removing leading / from absolute links");
  326.                         link_warn++;
  327.                     }
  328.                     link_name++;
  329.                 }
  330.                   strncpy(header->header.linkname,
  331.                     link_name,NAMSIZ);
  332.                 if(header->header.linkname[NAMSIZ-1]) {
  333.                     char *mangled;
  334.                     extern char *find_mangled();
  335.  
  336.                     mangled=find_mangled(link_name);
  337.                     msg("%s: link name too long: mangled to %s",link_name,mangled);
  338.                     strncpy(header->header.linkname,mangled,NAMSIZ);
  339.                 }
  340.                 header->header.linkflag = LF_LINK;
  341.                 finish_header(header);
  342.         /* FIXME: Maybe remove from list after all links found? */
  343.                 return;        /* We dumped it */
  344.             }
  345.         }
  346.  
  347.         /* Not found.  Add it to the list of possible links. */
  348.         lp = (struct link *)malloc((unsigned)(sizeof(struct link)+strlen(p)));
  349.         if (!lp) {
  350.             if (!nolinks) {
  351.                 msg(
  352.     "no memory for links, they will be dumped as separate files");
  353.                 nolinks++;
  354.             }
  355.         }
  356.         lp->ino = hstat.st_ino;
  357.         lp->dev = hstat.st_dev;
  358.         strcpy(lp->name, p);
  359.         lp->next = linklist;
  360.         linklist = lp;
  361.     }
  362.  
  363.     /*
  364.      * This is not a link to a previously dumped file, so dump it.
  365.      */
  366.     switch (hstat.st_mode & S_IFMT) {
  367.  
  368.     case S_IFREG:            /* Regular file */
  369. #ifdef S_IFCTG
  370.     case S_IFCTG:            /* Contiguous file */
  371. #endif
  372.     {
  373.         int    f;        /* File descriptor */
  374.         long    bufsize, count;
  375.         long    sizeleft;
  376.         register union re